import time
from datetime import datetime, timedelta

from flask import request, render_template, jsonify, current_app, redirect, url_for, g, session, abort

from info import db
from info.constants import ADMIN_USER_PAGE_MAX_COUNT, ADMIN_NEWS_PAGE_MAX_COUNT, QINIU_DOMIN_PREFIX
from info.models import User, News, Category
from info.modules.admin import admin_blu
from info.utils.common import user_login_data, file_upload
from info.utils.response_code import RET, error_map


@admin_blu.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'GET':
        # 取出来session的数据，id和is_admin,
        user_id = session.get('user_id')
        is_admin = session.get('is_admin')
        if user_id and is_admin:
            # 表示管理员已经登录，直接重定向到后台的首页
            return redirect(url_for('admin.index'))
        return render_template('admin/login.html')
    # post方法
    # 获取参数
    username = request.form.get("username")
    password = request.form.get("password")

    # 校验参数
    if not all([username, password]):
        print('1')
        return render_template('admin/login.html', errmsg="参数不足")
    # 根据username查询超级管理员
    try:
        user = User.query.filter(User.mobile == username, User.is_admin == True).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])
    if not user:
        return render_template("admin/login.html", errmsg="管理员不存在")

    # 校验密码
    if not user.check_password(password):
        return render_template('admin/login.html', errmsg="用户名与密码不正确")
    #
    session["user_id"] = user.id
    session["is_admin"] = True
    return redirect(url_for('admin.index'))


# 定义网站后台的首页
@admin_blu.route('/index')
@user_login_data
def index():
    user = g.user
    # 判断管理员是否登录

    return render_template('admin/index.html', user=user.to_dict())


# 定义后台退出登录
@admin_blu.route('/logout')
def logout():
    session.pop('user_id', None)
    session.pop('is_admin', None)
    # 管理员退出登录直接跳转到前台的首页
    return redirect(url_for('home.index'))


# 用户统计
@admin_blu.route('/user_count')
def user_count():
    # 用户总数
    total_count = 0
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 月新增总数,注册时间>=本月１号的0点

    # 获取当前时间的年和月
    t = time.localtime()

    # 构建目标日期的字符串-日期字符串
    date_mon_str = "%d-%02d-01" % (t.tm_year, t.tm_mon)
    # 将日期字符串转换成日期对象
    date_mon = datetime.strptime(date_mon_str, "%Y-%m-%d")

    mon_count = 0
    try:
        mon_count = User.query.filter(User.is_admin == False, User.create_time >= date_mon).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 日新增总数
    # 构建当天的日期字符串
    date_day_str = "%d-%02d-%02d" % (t.tm_year, t.tm_mon, t.tm_mday)
    # 将日期字符串转换成日期对象
    date_day = datetime.strptime(date_day_str, "%Y-%m-%d")
    day_count = 0
    try:
        day_count = User.query.filter(User.is_admin == False, User.create_time >= date_day).count()
    except BaseException as e:
        current_app.logger.error(e)

    # 　记录日注册活跃人数  注册时间>=今日0点<=次日0点
    active_count = []
    # 记录统计时间
    active_time = []
    for i in range(0, 30):
        begin_date = date_day - timedelta(days=i)
        end_date = date_day + timedelta(days=1) - timedelta(days=i)
        try:
            #
            one_day_count = User.query.filter(User.is_admin == False, User.create_time >= begin_date,
                                              User.create_time <= end_date).count()
            # 把遍历30次一个月每天的活跃人数加入列表
            active_count.append(one_day_count)

            # 将日期对象转为日期字符串
            ond_day_str = begin_date.strftime("%Y-%m-%d")
            # 把统计时间放进列表
            active_time.append(ond_day_str)
        except BaseException as e:
            current_app.logger.error(e)
    # 列表翻转
    active_count.reverse()
    active_time.reverse()
    data = {
        "total_count": total_count,
        "mon_count": mon_count,
        "day_count": day_count,
        "active_time": active_time,
        "active_count": active_count
    }

    return render_template('admin/user_count.html', data=data)


# 用户列表
@admin_blu.route('/user_list')
def user_list():
    # 分页查询所有的用户
    # 获取参数
    p = request.args.get('p', 1)
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)
    # 查询所有的用户数据
    try:
        pn = User.query.filter(User.is_admin == False).paginate(p, ADMIN_USER_PAGE_MAX_COUNT)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    data = {
        "user_list": [user.to_admin_dict() for user in pn.items],
        "cur_page": p,
        "total_page": pn.pages
    }
    return render_template('admin/user_list.html', data=data)


# 新闻审核列表
@admin_blu.route('/news_review')
def news_review():
    # 获取参数分页和关键字
    p = request.args.get('p', 1)
    keyword = request.args.get('keyword')
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)
    # 如果有关键字存在
    filter_list = []
    if keyword:
        filter_list.append(News.title.contains(keyword))
    # 查询所有的新闻数据
    try:
        pn = News.query.filter(*filter_list).paginate(p, ADMIN_NEWS_PAGE_MAX_COUNT)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "cur_page": p,
        "total_page": pn.pages
    }
    return render_template('admin/news_review.html', data=data)


# 新闻审核详情
@admin_blu.route('/news_review_detail<int:news_id>')
def news_review_detail(news_id):
    # 根据动态url传递来的新闻id查询新闻数据
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return abort(500)
    if not news:
        return abort(403)
    return render_template('admin/news_review_detail.html', news=news.to_dict())


# 新闻审核
@admin_blu.route('/news_review_action', methods=['POST'])
def news_review_action():
    # 参数新闻id和动作
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    # 校验
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    if action not in ['accept', 'reject']:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    try:
        news_id = int(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 根据新闻id查询新闻数据
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])
    if action == 'accept':
        news.status = 0
    else:
        news.status = -1
        reason = request.json.get('reason')
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
        news.reason = reason

    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 新闻编辑列表展示GET
@admin_blu.route('/news_edit')
def news_edit():
    # 获取参数,新闻编辑列表页码和关键字
    p = request.args.get("p", 1)
    keyword = request.args.get("keyword")
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    filter_list = []  # 是否有关键字
    if keyword:  # 搜索
        filter_list.append(News.title.contains(keyword))

    # 查询 所有的新闻数据
    try:
        pn = News.query.filter(*filter_list).paginate(p, ADMIN_USER_PAGE_MAX_COUNT)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)

    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "cur_page": p,
        "total_page": pn.pages
    }

    # 模板渲染
    return render_template("admin/news_edit.html", data=data)


# # 新闻编辑详情展示,GET使用查询字符串实现了功能
@admin_blu.route('/news_edit_detail')  # 动态url
def news_edit_detail():
    news_id = request.args.get('news_id')
    # 通过新闻id，查询到当前的新闻
    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)
    # 查询新闻信息
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    if not news:
        return abort(403)
    # 查询分类信息
    try:
        categories = Category.query.filter(Category.id != 1).all()
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)
    # TODO 标出这个新闻对应的当前分类信息
    category_list = []
    for category in categories:
        category_dict = category.to_dict()
        is_selected = False
        if category.id == news.category_id:
            is_selected = True
        category_dict['is_selected'] = is_selected
        category_list.append(category_dict)
    # 模板渲染
    return render_template('admin/news_edit_detail.html', news=news.to_dict(), category_list=category_list)


# 新闻编辑的提交post
@admin_blu.route('/news_edit_detail', methods=['POST'])
def news_edit_action():  # TODO 同一个蓝图实现的视图函数名不能相同, 函数标记会冲突
    # 获取参数
    news_id = request.form.get("news_id")
    title = request.form.get("title")
    category_id = request.form.get("category_id")
    digest = request.form.get("digest")
    content = request.form.get("content")
    index_image = request.files.get("index_image")
    # 校验参数
    if not all([news_id, title, category_id, digest, content]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 查询新闻模型
    try:
        news_id = int(news_id)
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    if not news:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 修改新闻数据--修改新闻数据的模型
    news.title = title
    news.digest = digest
    news.content = content
    news.category_id = category_id
    if index_image:  # 修改图片
        try:
            img_bytes = index_image.read()
            file_name = file_upload(img_bytes)
            news.index_image_url = QINIU_DOMIN_PREFIX + file_name
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.THIRDERR, errmsg=error_map[RET.THIRDERR])

    # json返回
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 修改分类
@admin_blu.route('/news_type', methods=['GET', 'POST'])
def news_type():
    if request.method == 'GET':
        # 查询所有的分类
        try:
            categories = Category.query.filter(Category.id != 1).all()
        except BaseException as e:
            current_app.logger.error(e)
            return abort(500)

        # 模板渲染
        return render_template("admin/news_type.html", categories=categories)

    # POST处理
    # 获取参数
    id = request.json.get("id")
    name = request.json.get("name")
    # 校验参数
    if not name:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    # 判断新增/修改  根据id
    if id:  # 修改分类信息
        # 查询分类, 修改数据
        try:
            id = int(id)
            category = Category.query.get(id)
        except BaseException as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

        category.name = name

    else:  # 新增分类信息
        new_category = Category()
        new_category.name = name
        db.session.add(new_category)

    # json返回
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])
